<?php

namespace app\common\command;

use app\common\enum\PayEnum;
use app\common\enum\RefundEnum;
use app\common\model\recharge\RechargeOrder;
use app\common\model\refund\RefundLog;
use app\common\model\refund\RefundRecord;
use app\common\service\pay\WeChatPayService;
use payment\SlashService;
use payment\WorldFirstService;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Log;
use think\facade\Db;
use app\common\model\finance\SlashTransactionRecord;
use app\common\model\card\{Card, CardBin};

class QueryRefund extends Command
{
    protected function configure()
    {
        $this->setName('query_refund')
            ->setDescription('订单退款状态处理');
    }


    protected function execute(Input $input, Output $output)
    {
        $this->slash_import();

//
//        $worldFirst = new WorldFirstService();
//        $hasMore = true;
//
//        $params = [
//            'page_number' => 1,
//            'page_size' => 20,
//        ];
//
//
//        while ($hasMore) {
//            dump($params);
//            $worldFirstResult = $worldFirst->getCardList($params);
//            $resultStatus = $worldFirstResult['result']['resultStatus'] ?? '';
//
//            // 检查是否有数据
//            if ($resultStatus != 'S') {
//                break;
//            }
//
//            // 处理当前页数据
//            foreach ($worldFirstResult['cardList'] as $item) {
//                $card_id = $item['assetId'];
//                $used_currency = $item['cardLimitDetail']['monthlyLimit']['used']['currency'];
//                $used_value = $item['cardLimitDetail']['monthlyLimit']['used']['value'];
//
//                $upd = Card::where('card_id', $card_id)->update(['used_value' => $used_value, 'used_currency' => $used_currency]);
//                dump($card_id . ' ' . $used_value . ' ' . $used_currency . ':update' . $upd);
//
//            }
//            dump($worldFirstResult['currentPageNumber']);
////            sleep(1);
//            // 检查是否还有下一页
//            $hasMore = $worldFirstResult['currentPageNumber'] < $worldFirstResult['totalPageNumber'];
//            $params['page_number'] = $params['page_number'] + 1;
//        }
    }

    function slash_import()
    {
        $contents = file_get_contents('slash_card.txt');
        $ids = explode("\r\n", $contents);
        $slashService = new SlashService(12);
        foreach ($ids as $k => $cardId) {
            dump($cardId);
            $cardId = trim($cardId);
            dump($cardId);
//            if ($k > 10) break;
            $count = Card::where('card_id', $cardId)->count();
            if ($count > 0) {
                dump('卡号已存在');
                file_put_contents('slash_card.log', $cardId.PHP_EOL, FILE_APPEND);
                continue;
            }

            $result = $slashService->getCardInfo($cardId, true);
            dump($result);
            if (isset($result['pan']) && $result['pan']) {
                $alias = $result['name'];
                $cardNum = $result['pan'];
                $cardStatus = ($result['status'] == 'active') ? 1 : 0;
                $cardSecure = json_encode([
                    'card_num' => $result['pan'],
                    'cvv' => $result['cvv'],
                    'expiry_month' => $result['expiryMonth'],
                    'expiry_year' => $result['expiryYear'],
                ]);


                $insert = Card::create([
                    'card_id' => $cardId,
                    'card_no' => $cardNum,
                    'card_bin' => 12,
                    'user_pid' => 0,
                    'user_id' => 39,
                    'available_balance' => $params['available_balance'] ?? 0,
                    'alias' => $alias ?? '',
                    'status' => $cardStatus ?? 1,
                    'card_nick_name' => '',
                    'card_group_id' => $params['card_group_id'] ?? '',
                    'group_id' => 63,
                    'tag_ids' => '',
                    'single_transaction_limit' => '0',
                    'daily_transaction_limit' => '0',
                    'monthly_transaction_limit' => '0',
                    'total_transaction_limit' => '0',
                    'create_time' => time(),
                ]);
                dump($insert . '导入 - 卡号: ' . $result['pan']);

                file_put_contents('slash_card.log', $result['pan'].PHP_EOL, FILE_APPEND);
                Card::where('card_id', $cardId)
                    ->update(['card_no' => $result['pan'], 'secure_msg' => encrypt($cardSecure)]);


                dump('slash敏感信息处理成功 - 卡号: ' . $result['pan']);

            } else {
                file_put_contents('slash_card.log', 'slash获取卡片信息失败 - 返回数据中缺少卡号信息'.PHP_EOL, FILE_APPEND);
                dump('slash获取卡片信息失败 - 返回数据中缺少卡号信息');

            }
        }

    }

    function world_first()
    {
        $cards = Card::where('card_bin', 10)
            ->where('status', 1)
            ->where('id', '>', 2900)
            ->select()
            ->toArray();
        $worldFirst = new WorldFirstService('worldfirst');
        foreach ($cards as $card) {
            sleep(1);
            $limitData = [
                'asset_id' => $card['card_id'],
                'per_transaction_limit_max' => $card['single_transaction_limit'] * 100,
                'daily_limit_max' => $card['daily_transaction_limit'] * 100,
                'monthly_limit_max' => $card['monthly_transaction_limit'] * 100,
                'per_card_limit_max' => $card['total_transaction_limit'] * 100,
            ];

            dump($limitData);
            Log::channel('worldfirst')->info('开始设置万里付卡片限额');
            Log::channel('worldfirst')->info(json_encode($limitData));

            $worldFirstResult = $worldFirst->updateCardLimit($limitData);

            if ($worldFirstResult['result']['resultStatus'] != 'S') {
                Log::channel('worldfirst')->error('万里付卡限额处理失败: ' . $worldFirstResult['result']['resultMessage']);
                dump($worldFirstResult['result']['resultMessage']);
                if ($worldFirstResult['result']['resultMessage'] == 'the card status is not ACTIVE, the current card status is FROZEN') {
                    $update = Card::where('card_id', $card['card_id'])->update(['status' => 0]);
                    dump($update);
                    continue;
                }
            }
            Log::channel('worldfirst')->info('万里付卡片限额设置成功');
            dump('万里付卡片限额设置成功');
        }
    }


    function slash()
    {
        $slash = new SlashService(12);
//        时间范围搜索有bug，此处屏蔽
        $params = [
//            'filter:from_date' => 1752148800000,
//            'filter:to_date' => 1752152399999,
//            'filter:status' => 'posted'
        ];
        $hasMore = true;
        $now = time();
        while ($hasMore) {
            $result = $slash->getTransaction($params);
            if (isset($result['items'])) {
                foreach ($result['items'] as $item) {
                    $timestamp = strtotime($item['date']);
                    if ($timestamp < $now - 86400) {
                        $hasMore = false;
                        break;
                    }

                    if (isset($item['cardId'])) {
//                        trace($item);
                        $this->slash_bill($item);
                    }
                }
            }
            if (isset($result['metadata']['nextCursor'])) {
                $params['cursor'] = $result['metadata']['nextCursor'];
            } else {
                $hasMore = false;
            }
        }
    }

    //slash交易记录
    function slash_bill($data)
    {
        //非卡片交易的不计算
        if (!isset($data['cardId'])) return;

        $transaction_id = $data['id'];

        $condition = [
            'transaction_id' => $transaction_id,
        ];

        $transaction_date = new \DateTime($data['date']);
        $transaction_date = $transaction_date->format('Y-m-d H:i:s');

        $posted_date = new \DateTime($data['authorizedAt']);
        $posted_date = $posted_date->format('Y-m-d H:i:s');

        $card = Card::where('card_id', $data['cardId'])
            ->field('card_id,card_no,user_id,group_id')
            ->findOrEmpty();

        //只记录系统开卡的交易记录
        file_put_contents('slash_card_other.txt', date('Y-m-d H:i:s') . PHP_EOL);
        if ($card->isEmpty()) {
            file_put_contents('slash_card_other.txt', $data['cardId'] . PHP_EOL, FILE_APPEND);
            return;
        }

        if ($data['amountCents'] < 0) {
            $transaction_amount = 0 - ($data['originalCurrency']['amountCents'] ?? 0) / 100;
        } else {
            $transaction_amount = ($data['originalCurrency']['amountCents'] ?? 0) / 100;
        }
        $row = [
            'status' => $data['status'],
            'transaction_amount' => $transaction_amount,
            'transaction_currency' => $data['originalCurrency']['code'] ?? '',
            'transaction_date' => $transaction_date,
            'transaction_type' => $data['detailedStatus'] ?? '',
            'billing_amount' => ($data['amountCents'] ?? 0) / 100,
            'billing_currency' => 'USD',

            'merchant_name' => $data['description'] ?? '',
            'card_id' => $data['cardId'] ?? '',
            'card_bin' => $data['card_bin'] ?? 12,
            'masked_card_number' => $card['card_no'] ?? '',
            'posted_date' => $posted_date,

            'user_id' => $card['user_id'] ?? 1,
            'group_id' => $card['group_id'] ?? 1,

            'location_city' => $data['merchantData']['location']['city'] ?? '',
            'location_country' => $data['merchantData']['location']['country'] ?? '',
            'location_state' => $data['merchantData']['location']['state'] ?? '',
            'location_zip' => $data['merchantData']['location']['zip'] ?? '',
        ];

        try {
            $transaction = SlashTransactionRecord::where($condition)->findOrEmpty();

            if ($transaction->isEmpty()) {
                SlashTransactionRecord::create(array_merge($condition, $row));
            } else {
                // 检查是否是pending变为reversed的情况
                $isStatusChanged = $transaction->transaction_type == 'pending' && $row['transaction_type'] == 'reversed';
                $update = $transaction->save($row);
                // 只在状态从pending变为reversed时才写日志
                if ($update && $isStatusChanged) {
                    file_put_contents('reversed.log', $transaction_id . "\t" . $row['billing_amount'] . "\n", FILE_APPEND);
                }
            }
        } catch (\Exception $e) {
            trace($e->getMessage(), 'error');
        }

    }

    /**
     * @notes 处理充值订单
     * @param $refundRecords
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @author 段誉
     * @date 2023/3/1 15:55
     */
    public function handleRechargeOrder($refundRecords)
    {
        $orderIds = array_unique(array_column($refundRecords, 'order_id'));
        $Orders = RechargeOrder::whereIn('id', $orderIds)->column('*', 'id');

        foreach ($refundRecords as $record) {
            if (!isset($Orders[$record['order_id']])) {
                continue;
            }

            $order = $Orders[$record['order_id']];
            if (!in_array($order['pay_way'], [PayEnum::WECHAT_PAY, PayEnum::ALI_PAY])) {
                continue;
            }

            $this->checkReFundStatus([
                'record_id' => $record['record_id'],
                'log_id' => $record['log_id'],
                'log_sn' => $record['log_sn'],
                'pay_way' => $order['pay_way'],
                'order_terminal' => $order['order_terminal'],
            ]);
        }
    }


    /**
     * @notes 校验退款状态
     * @param $refundData
     * @return bool
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @author 段誉
     * @date 2023/3/1 15:54
     */
    public function checkReFundStatus($refundData)
    {
        $result = null;
        switch ($refundData['pay_way']) {
            case PayEnum::WECHAT_PAY:
                $result = self::checkWechatRefund($refundData['order_terminal'], $refundData['log_sn']);
                break;
        }

        if (is_null($result)) {
            return false;
        }

        if (true === $result) {
            $this->updateRefundSuccess($refundData['log_id'], $refundData['record_id']);
        } else {
            $this->updateRefundMsg($refundData['log_id'], $result);
        }
        return true;
    }


    /**
     * @notes 查询微信支付退款状态
     * @param $orderTerminal
     * @param $refundLogSn
     * @return bool|string|null
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @author 段誉
     * @date 2023/3/1 15:47
     */
    public function checkWechatRefund($orderTerminal, $refundLogSn)
    {
        // 根据商户退款单号查询退款
        $result = (new WeChatPayService($orderTerminal))->queryRefund($refundLogSn);

        if (!empty($result['status']) && $result['status'] == 'SUCCESS') {
            return true;
        }

        if (!empty($result['code']) || !empty($result['message'])) {
            return '微信:' . $result['code'] . '-' . $result['message'];
        }

        return null;
    }


    /**
     * @notes 更新记录为成功
     * @param $logId
     * @param $recordId
     * @author 段誉
     * @date 2023/3/1 15:38
     */
    public function updateRefundSuccess($logId, $recordId)
    {
        // 更新日志
        RefundLog::update([
            'id' => $logId,
            'refund_status' => RefundEnum::REFUND_SUCCESS,
        ]);
        // 更新记录
        RefundRecord::update([
            'id' => $recordId,
            'refund_status' => RefundEnum::REFUND_SUCCESS,
        ]);
    }


    /**
     * @notes 更新退款信息
     * @param $logId
     * @param $msg
     * @author 段誉
     * @date 2023/3/1 15:47
     */
    public function updateRefundMsg($logId, $msg)
    {
        // 更新日志
        RefundLog::update([
            'id' => $logId,
            'refund_msg' => $msg,
        ]);
    }

}